package org.wx.thread.threadpool;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * @description: 使用 ThreadPoolExecutor 做100W的加法
 * @author: wangxun
 * @createDate: 2021/4/19
 * @version: 1.0
 */
@Slf4j
public class TpeSum {

    final static ThreadPoolExecutor wxTpe = new ThreadPoolExecutor(100, 100,
            0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(100),
            Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy());

    static volatile long mSum = 0;

    public static void main(String[] args) {


        reduce(1L,1000_0000L);
        singletonSum(1L,1000_0000L);
        try {
            new Thread(() -> {
                final long startTime = System.currentTimeMillis();
                while (true){
                    if(wxTpe.getActiveCount() == 0){
                        wxTpe.shutdown();
                        final long endTime = System.currentTimeMillis();
                        log.info("{}计算后的总数：{} 总用时：{}",Thread.currentThread().getName(),mSum,endTime-startTime);
                        break;
                    }
                }
            }).start();


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 分配任务
     * @param start 开始值
     * @param end 结束值
     */
    static void reduce(Long start, Long end){
        if(end - start >10000){
            // 多余1w
            reduce(start+10000,end);
        }
        FutureTask futureTask = new FutureTask<Long>(new Sum(start,start+9999));
        wxTpe.submit(futureTask);
        try {
            final Long temp = (Long) futureTask.get();
            mSum += temp;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }


    static class Sum implements Callable<Long>{

        private long startInt;
        private long endInt;

        public Sum(long startInt, long endInt) {
            this.startInt = startInt;
            this.endInt = endInt;
        }

        @Override
        public Long call() throws Exception {
            Long sum = 0L;
            for (long i = startInt; i < endInt; i++) {
                sum += i;
            }
            //log.info("{}计算后的总数：{}",Thread.currentThread().getName(),sum);
            return sum;
        }
    }



    /**
     * 对数器
     * @param start 开始值
     * @param end 结束值
     * @return 总数
     */
    static long singletonSum(long start, long end){
        final long startTime = System.currentTimeMillis();
        long sum = 0;
        for (long i = start; i < end; i++) {
            sum += i;
        }
        final long endTime = System.currentTimeMillis();
        log.info("单线程{}计算后的总数：{} 总用时：{}",Thread.currentThread().getName(),sum,endTime-startTime);
        return sum;
    }
}
